grammar Cobol;

file                    : ( ruleLine | line)* EOF
                        ;
//----------------------------------------------------------------------------
// RULELINE
//----------------------------------------------------------------------------
ruleLine                : stmt_fd
                        | stmt_move
                        | stmt_select
                        ;

stmt_fd                 : ( KW_FD | KW_SD ) ( OP_COMMA | OP_SEMI )? wd_ﾌｧｲﾙ名 ( KW_IS? KW_EXTERNAL | ws_文字列 )  (OP_DOT)? EOL ;
stmt_move               : KW_MOVE ( KW_CORR | KW_CORRESPONDING )? ws_move_origination KW_TO ws_move_destination  (OP_DOT)? EOL ;
stmt_select             : KW_SELECT ( KW_BASED | KW_EXTERNAL )? KW_OPTIONAL? wd_ﾌｧｲﾙ名 ( KW_ACCESS KW_MODE? KW_IS? ( KW_SEQUENTIAL | KW_DYNAMIC | KW_RANDOM ) ? | KW_ASSIGN KW_TO? ws_割り当て名 ? | ( KW_FILE | KW_STATUS | KW_RECORD | KW_PREFIX | KW_SEARCH | KW_ALTERNATE | KW_RESERVE | KW_WITH | KW_FLR | KW_VLR | KW_ULR ) ws_文字列 ? | ? ( KW_SEQUENTIAL | KW_INDEXED | KW_RELATIVE ) ? | KW_ORGANIZATION KW_IS? ( KW_SEQUENTIAL | KW_INDEXED | KW_RELATIVE ) ? )  (OP_DOT)? EOL ;

ws_move_destination     : wordList ;
ws_move_origination     : wordList ;
ws_割り当て名           : wordList ;
ws_文字列               : wordList ;
wd_ﾌｧｲﾙ名               : word ;

//----------------------------------------------------------------------------
// line
//----------------------------------------------------------------------------                       
line                    : wordList EOL
                        ;
//キー区分(tblSyntax.KeyKBN) = 2:可変部分
wordList                : (word)+
                        ;
//キー区分(tblSyntax.KeyKBN) = 6:単語の可変部分 
word                    : operator
                        | literal
                        | keyword
                        | Identifier 
                        ;
//----------------------------------------------------------------------------
// KEYWORD
//----------------------------------------------------------------------------
keyword                 : KW_ACCESS
                        | KW_ALTERNATE
                        | KW_ASSIGN
                        | KW_BASED
                        | KW_CORR
                        | KW_CORRESPONDING
                        | KW_DYNAMIC
                        | KW_EXTERNAL
                        | KW_FD
                        | KW_FILE
                        | KW_FLR
                        | KW_INDEXED
                        | KW_IS
                        | KW_MODE
                        | KW_MOVE
                        | KW_OPTIONAL
                        | KW_ORGANIZATION
                        | KW_PREFIX
                        | KW_RANDOM
                        | KW_RECORD
                        | KW_RELATIVE
                        | KW_RESERVE
                        | KW_SD
                        | KW_SEARCH
                        | KW_SELECT
                        | KW_SEQUENTIAL
                        | KW_STATUS
                        | KW_TO
                        | KW_ULR
                        | KW_VLR
                        | KW_WITH
                        ;
KW_ACCESS               : 'ACCESS' ;
KW_ALTERNATE            : 'ALTERNATE' ;
KW_ASSIGN               : 'ASSIGN' ;
KW_BASED                : 'BASED' ;
KW_CORR                 : 'CORR' ;
KW_CORRESPONDING        : 'CORRESPONDING' ;
KW_DYNAMIC              : 'DYNAMIC' ;
KW_EXTERNAL             : 'EXTERNAL' ;
KW_FD                   : 'FD' ;
KW_FILE                 : 'FILE' ;
KW_FLR                  : 'FLR' ;
KW_INDEXED              : 'INDEXED' ;
KW_IS                   : 'IS' ;
KW_MODE                 : 'MODE' ;
KW_MOVE                 : 'MOVE' ;
KW_OPTIONAL             : 'OPTIONAL' ;
KW_ORGANIZATION         : 'ORGANIZATION' ;
KW_PREFIX               : 'PREFIX' ;
KW_RANDOM               : 'RANDOM' ;
KW_RECORD               : 'RECORD' ;
KW_RELATIVE             : 'RELATIVE' ;
KW_RESERVE              : 'RESERVE' ;
KW_SD                   : 'SD' ;
KW_SEARCH               : 'SEARCH' ;
KW_SELECT               : 'SELECT' ;
KW_SEQUENTIAL           : 'SEQUENTIAL' ;
KW_STATUS               : 'STATUS' ;
KW_TO                   : 'TO' ;
KW_ULR                  : 'ULR' ;
KW_VLR                  : 'VLR' ;
KW_WITH                 : 'WITH' ;

//----------------------------------------------------------------------------
// OPERATOR
//----------------------------------------------------------------------------
operator                : OP_NOT_EQUAL2
                        | OP_DOLLAR
                        | OP_AMBER
                        | OP_LPAREN
                        | OP_LBRACK2
                        | OP_RPAREN
                        | OP_STAR
                        | OP_PLUS
                        | OP_COMMA
                        | OP_MINUS
                        | OP_DOT
                        | OP_RBRACK2
                        | OP_SLASH
                        | OP_COLON
                        | OP_ASSIGN
                        | OP_SEMI
                        | OP_LT
                        | OP_LE
                        | OP_NOT_EQUAL1
                        | OP_EQUAL
                        | OP_GT
                        | OP_GE
                        | OP_HELP
                        | OP_LBRACK
                        | OP_YEN
                        | OP_RBRACK
                        | OP_LCURLY
                        | OP_OR
                        | OP_RCURLY
                        | OP_NOT
                        ;
OP_NOT_EQUAL2           : '!=' ;
OP_DOLLAR               : '$' ;
OP_AMBER                : '&' ;
OP_LPAREN               : '(' ;
OP_LBRACK2              : '(.' ;
OP_RPAREN               : ')' ;
OP_STAR                 : '*' ;
OP_PLUS                 : '+' ;
OP_COMMA                : ',' ;
OP_MINUS                : '-' ;
OP_DOT                  : '.' ;
OP_RBRACK2              : '.)' ;
OP_SLASH                : '/' ;
OP_COLON                : ':' ;
OP_ASSIGN               : ':=' ;
OP_SEMI                 : ';' ;
OP_LT                   : '<' ;
OP_LE                   : '<=' ;
OP_NOT_EQUAL1           : '<>' ;
OP_EQUAL                : '=' ;
OP_GT                   : '>' ;
OP_GE                   : '>=' ;
OP_HELP                 : '?' ;
OP_LBRACK               : '[' ;
OP_YEN                  : '\\' ;
OP_RBRACK               : ']' ;
OP_LCURLY               : '{' ;
OP_OR                   : '|' ;
OP_RCURLY               : '}' ;
OP_NOT                  : '~' ;

//----------------------------------------------------------------------------
// Literal
//----------------------------------------------------------------------------
literal                 : numericLiteral
                        | nonnumericLiteral
                        ;
//キー区分(tblSyntax.KeyKBN) = 14:数字単語 
numericLiteral          : DecimalLiteral
                        | IntegerLiteral
                        ;
//キー区分(tblSyntax.KeyKBN) = 22:非数字単語 
nonnumericLiteral       : StringLiteral
                        | DbcsLiteral
                        | Utf8Literal
                        | HexNumber
                        | NullTerminated
                        ;
StringLiteral           : SingleQuotedString
                        | DoubleQuotedString
                        ;
DbcsLiteral             : ('G' | 'NX' | 'N') StringLiteral
                        ;
Utf8Literal             : ('UX' | 'U') StringLiteral
                        ;
HexNumber               : 'X' StringLiteral
                        ;
NullTerminated          : 'Z' StringLiteral
                        ;
IntegerLiteral          : ('+'|'-')?Digit+
                        ;
DecimalLiteral          : ('+'|'-')?Digit*('.')Digit+
                        ;
fragment
SingleQuotedString      : '\'' ('\'\'' | ~('\''))* '\''
                        ;
fragment
DoubleQuotedString      : '"' ('""' | ~('"'))* '"'
                        ;
//----------------------------------------------------------------------------
// ID
//----------------------------------------------------------------------------
//キー区分(tblSyntax.KeyKBN) = 54:ｱﾙﾌｧﾍﾞｯﾄ単語始る文字はA-Zまたはa-zの範囲内である）
Identifier              : (Alpha | '_' | Digit) (Alpha | Digit | '_' | '-')*
                        ;  
                        
fragment
Alpha                   : 'a'..'z'
                        | 'A'..'Z'
                        | '\u0080'..'\uFFFE' ~('\uFEFF') //ADDED unicode support
                        ;               
                        
fragment
Digit                   : '0'..'9'
                        ;
//----------------------------------------------------------------------------
// OTHER
//----------------------------------------------------------------------------
EOL                     : ('\r\n'|'\r'|'\n')+
                        ;
WS                      : (' '|'\t'|'\f')+ -> skip
                        ;
UnicodeBOM              : '\uFEFF' -> skip 
                        ;